using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.GamerServices;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Media;
using Microsoft.Xna.Framework.Net;
using Microsoft.Xna.Framework.Storage;

namespace qtAiGamesLibrary
{
    public class Utils
    {
        private static Random _rand;
        static Utils()
        {
            _rand = new Random(DateTime.Now.Millisecond);
        }
        /// <summary>
        /// Calculates whether the rotation will be positive or negative ;)
        /// </summary>
        /// <param name="From">From Vector</param>
        /// <param name="To">To Vector</param>
        /// <returns>1 or -1</returns>
        public static int Vector2Sign(Vector2 From, Vector2 To)
        {
            if ((From.Y*To.X) > (From.X*To.Y))
            {
                return -1;
            }
            else
            {
                return 1;
            }
        }

        /// <summary>
        /// Returns a random value between 1 and 0 from our global random stack
        /// </summary>
        /// <returns></returns>
        public static double RandPrecise()
        {
            return _rand.NextDouble();
        }

        /// <summary>
        /// Returns a number betwen -1 and  1;
        /// </summary>
        /// <returns></returns>
        public static double RandClamped()
        {
            return RandPrecise() - RandPrecise();
        }

        /// <summary>
        /// Get a number between 0 and the passed maxvalue
        /// </summary>
        /// <param name="MaxValue"></param>
        /// <returns></returns>
        public static int RandMax(int MaxValue)
        {
            return _rand.Next(MaxValue);
        }
        public class Transformations
        {

            /// <summary>
            /// A function to do rotation usign 2 vectors, side and fwd. I am sure I could do this differently
            /// but for now it will have to do!
            /// </summary>
            /// <param name="TargetMatrix"></param>
            /// <param name="fwd"></param>
            /// <param name="side"></param>
            /// <returns></returns>
            public static Matrix MatrixRotate(Matrix TargetMatrix, Vector2 fwd, Vector2 side)
            {
                Matrix mat = Matrix.Identity;

                mat.M11 = fwd.X;  mat.M12 = fwd.Y; mat.M13 = 0;
                //mat._11 = fwd.x;  mat._12 = fwd.y; mat._13 = 0;

                mat.M21 = side.X; mat.M22 = side.Y; mat.M23 = 0;
                //mat._21 = side.x; mat._22 = side.y; mat._23 = 0;

                mat.M31 = 0; mat.M32 = 0; mat.M33 = 1;
                //mat._31 = 0; mat._32 = 0;mat._33 = 1;

                //and multiply
                return Matrix.Multiply(TargetMatrix, mat);
            }

            //create a transformation matrix
            public static Matrix MatrixTranslate(Matrix TargetMatrix, float x, float y)
            {
             Matrix mat = Matrix.Identity;

              mat.M11 = 1; mat.M12 = 0; mat.M13 = 0;

              mat.M21 = 0; mat.M22 = 1; mat.M23 = 0;

              mat.M31 = x; mat.M32 = y; mat.M33 = 1;
              
              //and multiply
              return Matrix.Multiply(TargetMatrix, mat);
            }

            public static Vector2 TransformVector2(Matrix TransMatrix, Vector2 vPoint)
            {

                double tempX = (TransMatrix.M11 * vPoint.X) + (TransMatrix.M21 * vPoint.Y) + (TransMatrix.M31);

                double tempY = (TransMatrix.M12 * vPoint.X) + (TransMatrix.M22 * vPoint.Y) + (TransMatrix.M32);
              
                vPoint.X = (float)tempX;

                vPoint.Y = (float)tempY;

                return vPoint;
            }

            /// <summary>
            /// Transforms a point from the agent's local space into world space
            /// </summary>
            public static Vector2 PointToWorldSpace(Vector2 point,
                                                Vector2 AgentHeading,
                                                Vector2 AgentSide,
                                                Vector2 AgentPosition)
            {

	            //make a copy of the point
                Vector2 TransPoint = point;
              
                //create a transformation matrix
	            Matrix matTransform = Matrix.Identity;

	            //rotate
                matTransform = MatrixRotate(matTransform, AgentHeading, AgentSide);
                //matTransform.Rotate(AgentHeading, AgentSide);

	            //and translate
                //matTransform.Translate(AgentPosition.x, AgentPosition.y);
                matTransform = MatrixTranslate(matTransform, AgentPosition.X, AgentPosition.Y);

                //now transform the vertices
                //matTransform.TransformVector2Ds(TransPoint);
                TransPoint = TransformVector2(matTransform, TransPoint);
                    
                //Vector2.Transform(TransPoint, matTransform);
                
                return TransPoint;
            }

        }

        
    }
}
